package com.cskaoyan.javase.oop3._2inner._3local._4life;


/**
 * Variable 'a' is accessed from within inner class, needs to be final or effectively final
 * 在局部内部类当中访问作用域内部的局部变量,那么该局部变量要么直接声明final
 * 要么它就是一个实际意义上的常量(不修改就是实际意义上的常量)
 *
 * 为什么呢?为什么有这种语法设计呢?
 * 直接原因是: 局部变量和对象的生命周期冲突
 * 完全可能出现:
 *      局部变量已经随着方法调用完毕出栈销毁
 *      但是对象仍然存在,甚至该对象仍然要调用成员方法来访问局部变量
 *      那么该局部变量从哪里访问到呢?
 *
 * 为了解决生命周期的冲突问题,于是JVM在创建"访问了作用域内部局部变量的局部内部类对象时"
 * 会将该"被访问的局部变量"当成自身的成员变量存储
 * 于是,在后续局部变量被销毁,但对象仍然存在,并想要访问"该局部变量"时
 * 实际上访问的是对象中的"成员变量"
 *
 * 这和"这个被访问的局部变量是final,是常量"有什么关系呢?
 * 很多时候,为了解决一个问题,我们会提出并执行一个方案,于是我们就解决了一个问题
 * 但是,很有可能的就是: 这个解决问题的方案,它本身也是一个问题
 * 以上解决生命周期冲的问题的方案,会引入一个新的问题:
 *      1.从代码上来看,如果允许成员内部类修改作用域内部局部变量,那么修改的是局部变量的取值
 *      2.但是实际上修改的是成员变量的取值
 *      这里又存在一个冲突了
 *      如果允许修改,就必须将成员变量和局部变量的取值修改进行"同步".
 *      总之,Java的开发者没有采取"同步"的做法,而是干脆禁止了修改,将该局部变量设置为一个常量,这样就不会存在同步问题.
 *
 * 最后,补充一点:
 *      我们后面马上学习的匿名内部类,Lambda表达式,它们都是特殊的局部内部类
 *      这一个小细节 它们也需要注意
 *
 * @since 10:12
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        EnclosedClazz ec = new EnclosedClazz();
        // 该方法获取局部内部类的IA子类对象
        IA ia = ec.test();
        ia.testInner();
    }
}

class EnclosedClazz {
    public IA test() {
        int a = 10;
        class Inner implements IA {
            @Override
            public void testInner() {
                System.out.println(a);
            }
        }
        return new Inner();
    }
}

interface IA {
    public void testInner();
}